package com.ruyuan.homepage.server.service.impl;

import com.ruyuan.homepage.server.repository.bean.FinanceStatisticDO;
import com.ruyuan.homepage.server.repository.bean.FinanceStatisticExample;
import com.ruyuan.homepage.server.repository.mapper.FinanceStatisticMapper;
import com.ruyuan.homepage.server.service.FinanceStatisticService;
import com.ruyuan.homepage.server.service.model.FinanceIncreaseRateStatisticBO;
import com.ruyuan.homepage.server.service.model.FinanceStatisticBO;
import com.ruyuan.homepage.server.service.request.QueryFinanceIncreaseStatisticsParam;
import com.ruyuan.homepage.server.service.request.QueryFinanceStatisticsParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xx
 */
@Service
public class FinanceStatisticServiceImpl implements FinanceStatisticService {

    @Autowired
    private FinanceStatisticMapper mapper;

    @Override
    public List<FinanceStatisticBO> queryFinanceStatistics(QueryFinanceStatisticsParam param) {
        Integer statisticMonthCount = param.getStatisticMonthCount();
        if (statisticMonthCount == null || statisticMonthCount <= 0) {
            return new ArrayList<>();
        }
        List<String> dates = new ArrayList<>();
        Calendar curDate = GregorianCalendar.getInstance();
        for (int i = 0; i < statisticMonthCount; i++) {
            int year = curDate.get(Calendar.YEAR);
            int month = curDate.get(Calendar.MONTH) + 1;
            String date = year + "" + (month < 10 ? ("0" + month) : "" + month);
            dates.add(date);
            // 向前一个月, 再计算date
            curDate.add(Calendar.MONTH, -1);
        }
        FinanceStatisticExample financeStatisticExample = new FinanceStatisticExample();
        FinanceStatisticExample.Criteria criteria = financeStatisticExample.createCriteria();
        criteria.andRootOrgIdEqualTo(param.getRootOrgId());
        if (!CollectionUtils.isEmpty(param.getOrgIds())) {
            criteria.andOrgIdIn(param.getOrgIds());
        }
        criteria.andDateIn(dates);
        List<FinanceStatisticDO> financeStatisticDOS = mapper.selectByExample(financeStatisticExample);
        return financeStatisticDOS.stream().map(financeStatisticDO -> {
            FinanceStatisticBO financeStatisticBO = new FinanceStatisticBO();
            BeanUtils.copyProperties(financeStatisticDO, financeStatisticBO);
            return financeStatisticBO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<FinanceIncreaseRateStatisticBO> queryFinanceIncreaseRateStatistics(QueryFinanceIncreaseStatisticsParam param) {
        Calendar curDate = GregorianCalendar.getInstance();
        int year = curDate.get(Calendar.YEAR);
        int month = curDate.get(Calendar.MONTH) + 1;
        String curMonthStr = year + "" + (month < 10 ? ("0" + month) : "" + month);
        curDate.add(Calendar.MONTH, -1);
        year = curDate.get(Calendar.YEAR);
        month = curDate.get(Calendar.MONTH) + 1;
        String lastMonthStr = year + "" + (month < 10 ? ("0" + month) : "" + month);
        QueryFinanceStatisticsParam queryFinanceStatisticsParam = new QueryFinanceStatisticsParam();
        queryFinanceStatisticsParam.setStatisticMonthCount(2);
        queryFinanceStatisticsParam.setRootOrgId(param.getRootOrgId());
        queryFinanceStatisticsParam.setOrgIds(param.getOrgIds());
        List<FinanceStatisticBO> financeStatisticBOS = queryFinanceStatistics(queryFinanceStatisticsParam);
        Map<Long, List<FinanceStatisticBO>> statisticGroupByOrg = financeStatisticBOS.stream().collect(Collectors.groupingBy(FinanceStatisticBO::getOrgId));
        return statisticGroupByOrg.keySet().stream().map(orgId -> {
            List<FinanceStatisticBO> financeStatisticBOPair = statisticGroupByOrg.get(orgId);
            // 当前月统计
            Optional<FinanceStatisticBO> curMonthStatisticOp = financeStatisticBOPair.stream().filter(financeStatisticBO -> curMonthStr.equals(financeStatisticBO.getDate())).findFirst();
            // 上月统计
            Optional<FinanceStatisticBO> lastMonthStatisticOp = financeStatisticBOPair.stream().filter(financeStatisticBO -> lastMonthStr.equals(financeStatisticBO.getDate())).findFirst();
            FinanceIncreaseRateStatisticBO financeIncreaseRateStatisticBO = new FinanceIncreaseRateStatisticBO();
            if (curMonthStatisticOp.isPresent()) {
                FinanceStatisticBO curMonthStatistic = curMonthStatisticOp.get();
                financeIncreaseRateStatisticBO.setCurMonthCost(curMonthStatistic.getCost());
                financeIncreaseRateStatisticBO.setCurMonthProfit(curMonthStatistic.getProfit());
                financeIncreaseRateStatisticBO.setRootOrgId(curMonthStatistic.getRootOrgId());
                financeIncreaseRateStatisticBO.setOrgId(curMonthStatistic.getOrgId());
                financeIncreaseRateStatisticBO.setOrgName(curMonthStatistic.getOrgName());
            }
            if (lastMonthStatisticOp.isPresent()) {
                FinanceStatisticBO lastMonthStatistic = lastMonthStatisticOp.get();
                financeIncreaseRateStatisticBO.setLastMonthCost(lastMonthStatistic.getCost());
                financeIncreaseRateStatisticBO.setLastMonthProfit(lastMonthStatistic.getProfit());
                financeIncreaseRateStatisticBO.setRootOrgId(lastMonthStatistic.getRootOrgId());
                financeIncreaseRateStatisticBO.setOrgId(lastMonthStatistic.getOrgId());
                financeIncreaseRateStatisticBO.setOrgName(lastMonthStatistic.getOrgName());
            }
            Integer curMonthProfit = financeIncreaseRateStatisticBO.getCurMonthProfit();
            Integer lastMonthProfit = financeIncreaseRateStatisticBO.getLastMonthProfit();
            if(financeIncreaseRateStatisticBO.getLastMonthProfit() != null && curMonthProfit != null){
                BigDecimal profitIncrease = new BigDecimal(curMonthProfit - lastMonthProfit);
                // 利润增长率, 保留4位小数, 四舍五入
                financeIncreaseRateStatisticBO.setProfitIncreaseRate(profitIncrease.divide(new BigDecimal(lastMonthProfit), 4, RoundingMode.HALF_UP));
            }
            return financeIncreaseRateStatisticBO;
        }).collect(Collectors.toList());
    }
}
